package edu.friday.service.impl;

import edu.friday.common.constant.RoleConstants;
import edu.friday.common.result.RestResult;
import edu.friday.common.result.TableDataInfo;
import edu.friday.model.SysRole;
import edu.friday.model.vo.SysRoleVO;
import edu.friday.repository.SysRoleRepository;
import edu.friday.service.SysRoleService;
import edu.friday.utils.BeanUtils;
import edu.friday.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class SysRoleServiceImpl implements SysRoleService {
    @Autowired
    SysRoleRepository sysRoleRepository;

    @Override
    public List<SysRole> selectRoleAll() {
        return sysRoleRepository.findAll();
    }

    @Override
    public List<Long> selectRoleListByUserId(Long userId) {
        return sysRoleRepository.selectRoleIdsByUserId(userId);
    }



    @Override
    public TableDataInfo selectRoleList(SysRoleVO roleVO, Pageable page) {
        SysRole sysRole=new SysRole();
        BeanUtils.copyPropertiesIgnoreEmpty(roleVO,sysRole);
        sysRole.setDelFlag("0");
        ExampleMatcher exampleMatcher=ExampleMatcher.matching()
                .withMatcher("roleName",ExampleMatcher.GenericPropertyMatchers.contains());
        Example<SysRole> example=Example.of(sysRole,exampleMatcher);
        Page<SysRole> rs=sysRoleRepository.findAll(example,page);
        return TableDataInfo.success(rs.toList(),rs.getTotalElements());
    }

    @Override
    public String checkRoleNameUnique(String roleName) {
        SysRole sysRole=new SysRole();
        sysRole.setRoleName(roleName);
        return count(sysRole);
    }

    private String count(SysRole sysRole) {
        Example<SysRole> example=Example.of(sysRole);
        Long count=sysRoleRepository.count(example);
        if (count>0){
            return RoleConstants.NOT_UNIQUE;
        }
        return RoleConstants.UNIQUE;
    }

    @Override
    public String checkRoleKeyUnique(SysRoleVO sysRoleVO) {
        SysRole sysRole=new SysRole();
        BeanUtils.copyProperties(sysRoleVO,sysRole);
        return checkUnique(sysRole);
    }

    @Override
    @Transactional
    public RestResult insertRole(SysRoleVO sysRoleVO) {
        SysRole sysRole=new SysRole();
        BeanUtils.copyProperties(sysRoleVO,sysRole);
        sysRole.setDelFlag("0");
        sysRoleRepository.save(sysRole);
        sysRoleVO.setRoleId(sysRole.getRoleId());
        insertUserRole(sysRoleVO);
        return RestResult.success();
    }


    @Override
    public SysRole selectRoleMenuById(Long roleId) {
        SysRole sysRole=new SysRole();
        sysRole.setRoleId(roleId);
        sysRole.setDelFlag("0");
        return sysRoleRepository.findOne(Example.of(sysRole)).get();
    }

    public int updateStatus(Long roleId, String status) {
        return sysRoleRepository.saveStatus(roleId,status);
    }

    @Override
    public Set<String> selectRolePermissionByUserId(Long userId) {
        List<SysRole> perms=sysRoleRepository.selectRoleByUserId(userId);
        Set<String> permsSet=new HashSet<>();
        for (SysRole perm:perms) {
            if (StringUtils.isNotNull(perm)) {
                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
            }
        }
        return permsSet;
    }


    private int insertUserRole(SysRoleVO sysRoleVO) {
        Long[] menus=sysRoleVO.getMenuIds();
        if (StringUtils.isNull(menus)|| menus.length==0) {
            return 0;
        }
        Long[] roleIds=new Long[menus.length];
        Arrays.fill(roleIds,sysRoleVO.getRoleId());
        return sysRoleRepository.batchInsertUserRole(roleIds,menus);
    }

    private String checkUnique(SysRole sysRole) {
        Long roleId= StringUtils.isNull(sysRole.getRoleId())? -1L: sysRole.getRoleId();
        Example<SysRole> example=Example.of(sysRole);
        SysRole info=findOne(example);
        if (StringUtils.isNotNull(info)&&info.getRoleId().longValue()!=roleId.longValue()) {
            return RoleConstants.NOT_UNIQUE;
        }
        return RoleConstants.UNIQUE;
    }

    private SysRole findOne(Example<SysRole> example) {
        List<SysRole> list=sysRoleRepository.findAll(example, PageRequest.of(0,1)).toList();
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }
}
